package com.toolbox.alui.portalpages.browsing.portalprefs;

import com.plumtree.openfoundation.util.*;
import com.plumtree.openlog.OpenLogService;
import com.plumtree.openlog.OpenLogger;
import com.plumtree.portaluiinfrastructure.statichelpers.PTDebugHelpers;
import com.plumtree.server.*;
import com.plumtree.uiinfrastructure.activityspace.*;

/**
 * @author SudhaS
 */
public class PortalPrefsModel implements IPortalPrefsModel,
IPortalPrefsModelRO
{
	private static OpenLogger log = OpenLogService.GetLogger(
			OpenLogService.GetComponent(PTDebugHelpers.COMPONENT_PORTAL_BROWSING),
			"com.toolbox.alui.portalpages.browsing.portalprefs.PortalPrefsModel");
	
	public static final String STR_MVC_CLASS_NAME = "PortalPrefs";
	private static final String strPrefNamePrefix = "_";
	private static final int iPrefixLength = 1;
	private static final String strTrue = "true";
	private static final String strFalse = "false";
	private static final String strTextHTML = "text/html;charset=UTF-8";
	private static final String strTextXML = "text/xml;charset=UTF-8";
	private AActivitySpace m_asOwner;
	private IPTSession m_ptSession;
	private String m_strDisplayString;
	private String m_strContentType;
	private static final String strReturnXML = "<?xml version=\"1.0\"?><preferences>{0}</preferences>";
	private static final String strXMLPref = "<field><name><![CDATA[{0}]]></name><value><![CDATA[{1}]]></value></field>";
	private static final String strLeftBracket = "{";
	private static final String strRightBracket = "}";
	private static final int iBracketLength = 4;
	private static final String strEmptyString = "";

	public PortalPrefsModel()
	{
	}

	/**
	 * @see com.plumtree.uiinfrastructure.activityspace.IModel#CleanupTempData()
	 */
	public void CleanupTempData()
	{
	}

	/**
	 * @see com.plumtree.uiinfrastructure.activityspace.IModel#CleanupAllData()
	 */
	public void CleanupAllData()
	{
	}

	/**
	 * @see com.plumtree.uiinfrastructure.activityspace.IManagedObject#Create()
	 */
	public Object Create()
	{
		return new PortalPrefsModel();
	}

	/**
	 * @see com.plumtree.portaluiinfrastructure.activityspace.IModelRO#GetName()
	 */
	public String GetName()
	{
		return STR_MVC_CLASS_NAME;
	}

	/**
	 * @see com.plumtree.portaluiinfrastructure.activityspace.IModel#Init(AActivitySpace)
	 */
	public void Init(AActivitySpace _asOwner)
	{
		m_asOwner		 = _asOwner;
		m_ptSession		 = (IPTSession) m_asOwner.GetUserSession();
		m_strDisplayString = strFalse;
		m_strContentType = strTextHTML;

	}

	public String GetDisplayString()
	{
		return m_strDisplayString;
	}

	public String GetContentType()
	{
		return m_strContentType;
	}
	
	
	/*
	 * 
	 * Format The following way:
	 * Object [][] arValues = new Object[2][1];
	 * arValues[0][i] = strName;
	 * arValues[1][i] = oValue;
	 * 
	 */
	private Object[][] formatNameValuePair(XPHashtable preferences){
		IXPDictionaryEnumerator prefs = preferences.GetEnumerator();

		Object[] arrPrefsNames = new Object[preferences.GetSize()];
		Object[] arrPrefsValues = new Object[preferences.GetSize()];
		
		int i = 0;
		while (prefs.MoveNext())
		{
			IXPDictionaryEntry preference = prefs.GetCurrentDictionaryEntry();
			String strPrefName = (String) preference.GetKey();

			//All real session prefs will begin with a special token (underscore)
			//this is so that they won't be confused with regular parameters (space, control, etc.).
			if (null != strPrefName && strPrefName.startsWith(strPrefNamePrefix))
			{
				// get the value
				String[] strPrefValue = (String[]) preference.GetValue();

				// take off the underscore
				strPrefName = strPrefName.substring(iPrefixLength);

				//store the name and the value in the array
				arrPrefsNames[i] = strPrefName;
				arrPrefsValues[i] = strPrefValue[0];

				i++;
			}
		}
		
		//package the pref into a well sized array
		Object[][] arrPrefs = new Object[2][i];
		for(int j=0;j<i;j++){
			arrPrefs[0][j] = arrPrefsNames[j];
			arrPrefs[1][j] = arrPrefsValues[j];
		}

		return arrPrefs;
	}
	
	/*
	 * 
	 * Format The following way:
	 * Object [][] arValues = new Object[2][1];
	 * arValues[i][0] = strName;
	 * arValues[i][1] = oValue;
	 * 
	 */
	private String[][] formatSessionNameValuePair(XPHashtable preferences){
		IXPDictionaryEnumerator prefs = preferences.GetEnumerator();

		Object[] arrPrefsNames = new Object[preferences.GetSize()];
		Object[] arrPrefsValues = new Object[preferences.GetSize()];
		
		int i = 0;
		while (prefs.MoveNext())
		{
			IXPDictionaryEntry preference = prefs.GetCurrentDictionaryEntry();
			String strPrefName = (String) preference.GetKey();

			//All real session prefs will begin with a special token (underscore)
			//this is so that they won't be confused with regular parameters (space, control, etc.).
			if (null != strPrefName && strPrefName.startsWith(strPrefNamePrefix))
			{
				// get the value
				String[] strPrefValue = (String[]) preference.GetValue();

				// take off the underscore
				strPrefName = strPrefName.substring(iPrefixLength);

				//store the name and the value in the array
				arrPrefsNames[i] = strPrefName;
				arrPrefsValues[i] = strPrefValue[0];

				i++;
			}
		}

		//package the pref into a well sized array
		String[][] arrPrefs = new String[i][2];
		for(int j=0;j<i;j++){
			arrPrefs[j][0] = arrPrefsNames[j].toString();
			arrPrefs[j][1] = arrPrefsValues[j].toString();
		}
		
		return arrPrefs;
	}
	
	private String[] formatHashtableToNameArray(XPHashtable preferences){
		IXPDictionaryEnumerator prefs = preferences.GetEnumerator();

		//Guesstimate the length of session pref names array to be the size of hashtable.
		String[] arrPrefNames = new String[preferences.GetSize()];
		int i = 0;

		//Get all session pref names into an array.
		while (prefs.MoveNext())
		{
			IXPDictionaryEntry preference = prefs.GetCurrentDictionaryEntry();
			String strPrefName = (String) preference.GetKey();

			//All real session prefs will begin with a special token (underscore)
			//this is so that they won't be confused with regular parameters (space, control, etc.).
			if (strPrefName.startsWith(strPrefNamePrefix))
			{
				arrPrefNames[i] = strPrefName.substring(iPrefixLength);
				i++;
			}
		}
		
		//package the pref into a well sized array
		String[] arrFullPrefNames = new String[i];
		for(int j=0;j<i;j++){
			arrFullPrefNames[j] = arrPrefNames[j];
		}
		
		return arrFullPrefNames;
	}

	private void packageValuesInXML(Object[][] arrPrefValues){
		//get the size of the array
		int i = arrPrefValues[0].length;

		//this array will hold the field name-value pair strings.
		String[] arrPrefElements = new String[i];
		//this string will consist of {0}{1}{2} etc.. for the number of fields there are.
		XPStringBuilder strPrefElementsFormatString = new XPStringBuilder (i*iBracketLength);
		//this array will hold name and value for formatting each field.
		Object[] arrPrefNameValue = new Object[2];
		for (int j = 0; j < i; j++)
		{
			// Get the pref name and value
			arrPrefNameValue[0] = arrPrefValues[0][j];
			arrPrefNameValue[1] = arrPrefValues[1][j];
			//if the pref value is null, we want to replace it with an empty string.
			if (arrPrefNameValue[1] == null)
			{
				arrPrefNameValue[1] = strEmptyString;
			}
			// generate the <field> ... </field> XML string
			arrPrefElements[j] = XPFormat.Format(strXMLPref, arrPrefNameValue);
			// add to the big format string
			strPrefElementsFormatString.Append(strLeftBracket);
			strPrefElementsFormatString.Append(XPConvert.ToString(j));
			strPrefElementsFormatString.Append(strRightBracket);
		}

		//Now let's chunk together all the field values
		String[] arrAllFields = new String[1];
		arrAllFields[0] = XPFormat.Format(strPrefElementsFormatString.toString(), arrPrefElements);
		//and put it into the final xml string.
		m_strDisplayString = XPFormat.Format(strReturnXML, arrAllFields);
		m_strContentType = strTextXML;
	}
	
	public void SetSessionPrefs(XPHashtable preferences)
	{
		try{
			//need to move all the preferences into a 2D array
			String[][] arrPrefs = formatSessionNameValuePair(preferences);

			if (arrPrefs.length > 0 && arrPrefs[0][0] != null)
			{
				boolean bSetPrefs = m_ptSession.GetSessionInfo().AddSessionPreferences(arrPrefs, true);

				// set the result
				if (bSetPrefs)
				{
					m_strDisplayString = strTrue;
				}
			}
		}catch(Exception exc){
			log.Error("An error occured while saving session preference.", exc);
			throw new XPException(exc);
		}
	}
	
	public void SetPortletPrefs(XPHashtable preferences, int portletID)
	{
		try{
			boolean bSetPrefs = false;
			//need to move all the preferences into a 2D array
			Object[][] arrPrefs = formatNameValuePair(preferences);

			if (arrPrefs.length > 0 && arrPrefs[0][0] != null && portletID >= 0)
			{
				m_ptSession.GetSessionInfo().AssignPreferences(arrPrefs, false, portletID);
				bSetPrefs = true;
				
				// set the result
				if (bSetPrefs)
				{
					m_strDisplayString = strTrue;
				}
			}
		}catch(Exception exc){
			log.Error("An error occured while saving portlet preference.", exc);
			throw new XPException(exc);
		}
	}
	
	public void SetUserPrefs(XPHashtable preferences)
	{
		//if portletid is 0, it sets a user preference
		SetPortletPrefs(preferences,0);
	}
	
	public void GetPortletPrefs(XPHashtable preferences, int portletID)
	{
		try{
			String[] arrSessionPrefNames = formatHashtableToNameArray(preferences);
			
			//Get pref values.
			Object[][] arrPrefValues;
			if (arrSessionPrefNames.length > 0 && arrSessionPrefNames[0] != null && portletID >= 0)
			{
				arrPrefValues = m_ptSession.GetSessionInfo().LookupPreferences(arrSessionPrefNames, portletID);

				//Now, let's generate the XML.
				packageValuesInXML(arrPrefValues);
			}
		}catch(Exception exc){
			log.Error("An error occured while getting portlet preference.", exc);
			throw new XPException(exc);
		}
	}
	
	public void GetUserPrefs(XPHashtable preferences)
	{
		//if portletid is 0, it sets a user preference
		GetPortletPrefs(preferences, 0);
	}

	public void GetSessionPrefs(XPHashtable preferences)
	{
		try{
			String[] arrSessionPrefNames = formatHashtableToNameArray(preferences);
			
			//Get pref values.
			String[][] arrPrefValues;
			if (arrSessionPrefNames.length > 0 && arrSessionPrefNames[0] != null)
			{
				arrPrefValues = m_ptSession.GetSessionInfo().LookupSessionPreferences(arrSessionPrefNames, true);

				//Now, let's generate the XML.
				packageValuesInXML(arrPrefValues);
			}
		}catch(Exception exc){
			log.Error("An error occured while getting portlet preference.", exc);
			throw new XPException(exc);
		}
	}

	public void GetCommunityPortletPrefs(XPHashtable preferences, int communityID, int portletID) {
		try{
			String[] arrSessionPrefNames = formatHashtableToNameArray(preferences);
			
			//Get pref values.
			Object[][] arrPrefValues;
			if (arrSessionPrefNames.length > 0 && arrSessionPrefNames[0] != null)
			{
				arrPrefValues = (Object[][]) ((IPTCommunityManager)m_ptSession.GetCommunities()).CachedOpenCommunityInfo(communityID, true)
				.LookupPreferences(arrSessionPrefNames, portletID, PT_PREF_TYPES.PT_PREFTYPE_ALL_USERS);

				//Now, let's generate the XML.
				packageValuesInXML(arrPrefValues);
			}
		}catch(Exception exc){
			log.Error("An error occured while getting portlet preference.", exc);
			throw new XPException(exc);
		}
	}

	public void GetCommunityPrefs(XPHashtable preferences, int communityID) {
		//if portletid is 0, it sets a user preference
		GetCommunityPortletPrefs(preferences, communityID, 0);
	}

	public void SetCommunityPortletPrefs(XPHashtable preferences, int communityID, int portletID) {
		try{
			boolean bSetPrefs = false;
			//need to move all the preferences into a 2D array
			Object[][] arrPrefs = formatNameValuePair(preferences);

			if (arrPrefs.length > 0 && arrPrefs[0][0] != null && portletID >= 0)
			{
				((IPTCommunity)m_ptSession.GetCommunities().Open(communityID, false))
				.AssignPreferences(arrPrefs, false, portletID, PT_PREF_TYPES.PT_PREFTYPE_ALL_USERS);
				
				bSetPrefs = true;
				
				// set the result
				if (bSetPrefs)
				{
					m_strDisplayString = strTrue;
				}
			}
		}catch(Exception exc){
			log.Error("An error occured while saving portlet preference.", exc);
			throw new XPException(exc);
		}
	}

	public void SetCommunityPrefs(XPHashtable preferences, int communityID) {
		//if portletid is 0, it sets a user preference
		SetCommunityPortletPrefs(preferences, communityID, 0);
	}

	public void GetAdminPortletPrefs(XPHashtable preferences, int portletID) {
		try{
			String[] arrSessionPrefNames = formatHashtableToNameArray(preferences);
			
			//Get pref values.
			Object[][] arrPrefValues;
			if (arrSessionPrefNames.length > 0 && arrSessionPrefNames[0] != null)
			{
				IPTGadget portlet = (IPTGadget) m_ptSession.GetGadgets().Open(portletID, false);
				IPTAdminSettings ptAdminSettings = (IPTAdminSettings) portlet.GetInterfaces("IPTAdminSettings");
				
				arrPrefValues = (Object[][]) ptAdminSettings.LookupAdminGadgetSettings(arrSessionPrefNames);
				
				//Now, let's generate the XML.
				packageValuesInXML(arrPrefValues);
			}
		}catch(Exception exc){
			log.Error("An error occured while getting portlet preference.", exc);
			throw new XPException(exc);
		}
	}

	public void SetAdminPortletPrefs(XPHashtable preferences, int portletID) {
		try{
			boolean bSetPrefs = false;
			//need to move all the preferences into a 2D array
			Object[][] arrPrefs = formatNameValuePair(preferences);

			if (arrPrefs.length > 0 && arrPrefs[0][0] != null && portletID >= 0)
			{
				IPTGadget portlet = (IPTGadget) m_ptSession.GetGadgets().Open(portletID, false);
				IPTAdminSettings ptAdminSettings = (IPTAdminSettings) portlet.GetInterfaces("IPTAdminSettings");
				
				for(int i=0; i<arrPrefs[0].length;i++){
					ptAdminSettings.AddAdminGadgetSetting((String)arrPrefs[0][i], arrPrefs[1][i]);
				}
				
				bSetPrefs = true;
				
				// set the result
				if (bSetPrefs)
				{
					m_strDisplayString = strTrue;
				}
			}
		}catch(Exception exc){
			log.Error("An error occured while saving portlet preference.", exc);
			throw new XPException(exc);
		}
	}
}

